import axios from 'axios'
import jsonBig from 'json-bigint'
// 在非组件内使用store的state数据 引入store
import store from '@/store'
// 复制axios 用create方法 并在新建的实例中添加基地址
import router from '@/router'

const request = axios.create({
  baseURL: 'http://ttapi.research.itcast.cn/'
})
// 准备请求拦截器 和 响应拦截器
request.interceptors.request.use(config => {
  const userToken = store.state.user
  if (userToken) {
    config.headers.Authorization = `Bearer ${userToken.token}`
  }
  return config
}, function (error) {
  return Promise.reject(error)
})
request.interceptors.response.use(config => {
  return config
},
async function (error) {
  // return Promise.reject(error)
  if (error.response && error.response.status === 401) {
    // 在vuex中获取 user
    const user = store.state.user
    // 如果user不存在 或是refresh_token失效 跳转登录重新获取
    if (!user || !user.refresh_token) {
      // router.push('/login')
      redirectLogin()
      // 以后代码不执行
      return
    }
    // 如果refresh_token存在的 重新获取token
    try {
      // 这里使用axios 是因为request实例上有请求拦截 而这时token失效 无法发送请求
      // 所以用axios本身请求新的token
      const res = await axios({
        method: 'PUT',
        url: 'http://ttapi.research.itcast.cn/app/v1_0/authorizations',
        headers: {
          Authorization: `Bearer ${user.refresh_token}`
        }
      })
      // 修改vuex的state 需要交给motions处理 获取成功将容器的token更新
      store.commit('setUser', {
        token: res.data.data.token, // 更新token
        refresh_token: user.refresh_token // 用原来的
      })
      // 把之前失败的用户请求继续发出去
      // config 是一个对象，其中包含本次失败请求相关的那些配置信息，例如 url、method 都有
      // return 把 request 的请求结果继续返回给发请求的具体位置
      // 获取到新的token后 把request的失败请求对象再次 用request实例发出
      // 避免用户点击两次才有请求成功的状况发生
      return request(error.config)
    } catch (err) {
      // router.push('/login')
      redirectLogin()
    }
  }
  return Promise.reject(error)
})
// router.currentRoute 当前路由对象，和你在组件中访问的 this.$route 是同一个东西
function redirectLogin () {
  router.push('/login?redirect=' + router.currentRoute.fullPath)
}
// 把处理大数字的方法准备出来
request.defaults.transformResponse = [function (data) {
  try {
    return jsonBig.parse(data)
  } catch (error) {
    return {}
  }
}]
export default request
